package server;

import com.alibaba.fastjson.JSONObject;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import io.netty.handler.codec.http.websocketx.WebSocketFrame;
import io.netty.util.concurrent.DefaultPromise;
import io.netty.util.concurrent.EventExecutor;
import io.netty.util.concurrent.Promise;
import lombok.extern.slf4j.Slf4j;
import model.Message;
import org.apache.commons.lang3.StringUtils;

import java.util.Objects;

/**
 * @author yujie
 * @createTime 2023/2/23 14:53
 * @description
 */
@Slf4j
@ChannelHandler.Sharable
public class WebSocketFrameHandler extends SimpleChannelInboundHandler<WebSocketFrame> {

    public static OpenAiClient openAiClient;
    public static ThirdClient thirdClient;

    public static int trynumber = 0;

    @Override
    public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
        super.channelRegistered(ctx);
    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        super.channelActive(ctx);
    }

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, WebSocketFrame webSocketFrame) throws Exception {
        if (webSocketFrame instanceof TextWebSocketFrame) {
            String request = ((TextWebSocketFrame) webSocketFrame).text();
            log.info("====服务端成功接受文本ws消息=====:{}", request);
            Message message = JSONObject.parseObject(request, Message.class);
            if(StringUtils.equals(message.getType(), "client_req")){
                //如果是第三方客户端发来的请求将发给openai
                thirdClient = new ThirdClient(ctx.channel());
                openAiClient.getChannel().writeAndFlush(new TextWebSocketFrame(message.getMsg()));
            }else if(StringUtils.equals(message.getType(), "remember_me")){
                //不稳定的情况下记住当前可用的channel
                openAiClient = new OpenAiClient(ctx.channel());
                //出现新连接
                Promise<Object> waitOpen = ThirdClient.map.remove("WAIT_OPEN");
                if(Objects.nonNull(waitOpen)){
                    log.info("页面重新刷新之后，主动断开之前的ws连接");
                    waitOpen.setSuccess("连接成功");
                }
            }else if(StringUtils.equals("openai_rep", message.getType())){
                //接受openai的响应
                Promise<Object> waitRetryRep = ThirdClient.map.remove("WAIT_RETRY_REP");
                if(Objects.nonNull(waitRetryRep)){
                    waitRetryRep.setSuccess(message);
                }else{
                    thirdClient.getChannel().writeAndFlush(new TextWebSocketFrame(message.getMsg()));
                }
            }else if(StringUtils.equals("error", message.getType())){
//                if(StringUtils.equals("Cannot read properties of null (reading 'nextSibling')", message.getMsg())){
//                    //openai发来消息由于按钮问题无法生成文本，通知浏览器重新刷新页面
//                    Channel channel = openAiClient.getChannel();
//                    channel.writeAndFlush(new TextWebSocketFrame("refresh_page"));
//                    DefaultPromise<Object> promise = new DefaultPromise<Object>(channel.eventLoop());
//                    ThirdClient.map.put("WAIT_RETRY", promise);
//                    promise.await();
//                    Channel promiseNow = (Channel) promise.getNow();
//                    promiseNow.writeAndFlush(new TextWebSocketFrame(message.getMsg()));
//                }else{
                    //出现异常1个小时后再重试
                    log.error("请求chatgpt被拒绝，等待一个小时后恢复");
                    Promise<Object> waitRep = ThirdClient.map.remove("WAIT_REP");
                    waitRep.setSuccess("error");
                    trynumber++;
//                }

            }else if(StringUtils.equals("retry_req", message.getType())){
                //openai发来消息由于按钮问题无法生成文本，通知浏览器重新刷新页面
                Channel channel = openAiClient.getChannel();
                channel.writeAndFlush(new TextWebSocketFrame("refresh_page"));
                EventLoopGroup group = new NioEventLoopGroup();
                Promise<Object> waitOpen = new DefaultPromise<>(group.next());
                ThirdClient.map.put("WAIT_OPEN", waitOpen);
                log.info("收到重新发送的请求，通知浏览器刷新，重新建立连接，再次发送消息");
                waitOpen.await();
                openAiClient.getChannel().writeAndFlush(new TextWebSocketFrame(message.getMsg()));
            }else if(StringUtils.equals("refresh_success", message.getType())){
                openAiClient.getChannel().closeFuture().addListener(ChannelFutureListener.CLOSE_ON_FAILURE);
            }
        }
    }


    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        log.info("断开连接：{}", ctx.channel().remoteAddress().toString());
        super.exceptionCaught(ctx, cause);
    }
}
